package cn.jisol.ngame.actions.statesync;

import cn.jisol.ngame.actions.statesync.entity.FilterSyncData;
import cn.jisol.ngame.actions.statesync.entity.NFrameData;
import cn.jisol.ngame.actions.statesync.client.NStateSyncClient;
import cn.jisol.ngame.ncall.NCallServiceImpl;
import cn.jisol.ngame.rpc.NGameRPCClass;
import cn.jisol.ngame.rpc.NGameRPCMethod;
import cn.jisol.ngame.rpc.NRPCParam;
import cn.jisol.ngame.rpc.action.NBackAsync;
import cn.jisol.ngame.sync.NFPSInfo;
import cn.jisol.ngame.sync.bridge.NSyncBridgeMode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;

import java.util.*;

@Getter
@Setter
@Component
@NGameRPCClass
public class SNStateSyncAction extends NCallServiceImpl {
    
    
    //房主
    public NStateSyncClient owner = null;
    //玩家
    public Map<String,NStateSyncClient> clients = new HashMap<>();
    
    //同步nSyncModes
    public NSyncBridgeMode<NFrameData> nSyncBridgeMode = null;
    
    /**
     * 切换角色
     * @return 返回是否设置成功
     */
    @NGameRPCMethod
    public String onSwitchRole(NStateSyncClient client){
        
        System.out.println("SNWorld2Action - onSwitchRole");
        
        //如果没有房主则设置房主
        if(Objects.isNull(this.owner)){
            this.owner = client;
            client.setRole(NStateSyncClient.Role.OWNER);
            //有房主之后开启同步
            this.nGameSyncStart();
        }else{
            this.clients.put(client.getUuid(),client);
            client.setRole(NStateSyncClient.Role.PLAYER);
        }
        
        return client.getRole().toString();
        
    }
    
    @NGameRPCMethod
    public void onSendServerMessage(@NRPCParam("event") Object event){
        System.out.println("SNWorld2Action - onSendServerMessage");
        
        //向房主发送消息
        if(Objects.nonNull(this.owner))
            this.owner.getCnStateSyncAction().onReceServerMessage(event);
        
    }
    
    
    /**
     * 启动桥接同步
     */
    public void nGameSyncStart(){
        
        if(Objects.nonNull(nSyncBridgeMode)) return;
        
        //创建帧同步对象
        nSyncBridgeMode = new NSyncBridgeMode<>();
        
        //添加同步功能
        addRegister(nSyncBridgeMode);
        
        //开启同步
        nSyncBridgeMode.start();
        System.out.println("SNCocosFrameAction - nGameSyncStart : 启动桥接同步");
        
    }
    
    /**
     * 向同步帧添加数据(Owner) 并 推送所有玩家
     */
    @NGameRPCMethod
    public void nPushSyncData(NStateSyncClient client,@NRPCParam("data") NFPSInfo<NFrameData> data){
        
        //如果不是Owner 则 无法推送
        if(!(NStateSyncClient.Role.OWNER.equals(client.getRole())) || Objects.isNull(nSyncBridgeMode)) return;
        
//        System.out.println("SNCocosFrameAction - nPushSyncData");
        
        nSyncBridgeMode.addFPSInfo(data);
        this.clients.forEach((String key,NStateSyncClient NStateSyncClient) -> {
            NFPSInfo<NFrameData> clone = data.clone();
            NStateSyncClient.getFilters().forEach(filterSyncData -> {
                clone.getDs().removeIf(filterSyncData::filter);
            });
            NStateSyncClient.getCnStateSyncAction().onReceSyncData(clone);
        });
        
    }
    
    /**
     * 设置同步数据过滤
     */
    @NGameRPCMethod
    public void nFilterSyncData(NStateSyncClient client, @NRPCParam("filter") FilterSyncData filter){
        if(filter.getIsClean()){
            client.getFilters().removeIf(filterSyncData -> Objects.equals(filterSyncData.getType(), filter.getType()));
        }
        client.getFilters().add(filter);
    }
    
    /**
     * 更新新数据
     */
    @NGameRPCMethod
    public void nUpdateLastInfo(@NRPCParam("data") NFPSInfo<NFrameData> lastInfo){
        
        Number index = lastInfo.getI();
        
        //清除小于index的数据
        NFPSInfo<NFrameData> frame = null;
        Iterator<NFPSInfo<NFrameData>> iterator = nSyncBridgeMode.getDataList().iterator();
        while (Objects.nonNull(frame = iterator.next())){
            if(frame.getI().intValue() < index.intValue()){
                nSyncBridgeMode.getDataList().remove(frame);
            }
        }
        
        //更新最新数据
        nSyncBridgeMode.setLastInfo(lastInfo);
        
    }
    
    /**
     * 获取String最新世界信息
     */
    @NGameRPCMethod
    public String nGetString(NStateSyncClient client){
    
        client.getCnStateSyncAction().nGetString().async(
            data -> {
                System.out.println("SNStateSyncAction-nGetSyncWorld Return: " + data);
            }
        );
        
        return "Hello Return";
        
    }
    
    /**
     * 获取异步房主最新世界信息
     */
    @NGameRPCMethod
    public NBackAsync<Object> nGetSyncWorld(NStateSyncClient client){
    
        if (Objects.nonNull(this.owner))
            return this.owner.getCnStateSyncAction().nGetSyncWorld();
        else
            return null;
    }
    
    /**
     * 获取最新数据
     */
    @NGameRPCMethod
    public NFPSInfo<NFrameData> nGetLastData(){
        return nSyncBridgeMode.getLastInfo();
    }
    
    /**
     * 获取帧数据
     */
    @NGameRPCMethod
    public List<NFPSInfo<NFrameData>> nGetSyncFrame(@NRPCParam("start") int start, @NRPCParam("end") int end){
        return nSyncBridgeMode.vGetFrame(start,end);
    }


}
